using System;
using System.Collections.Generic;
using System.Linq;
using FwkLight.Domain;

namespace FwkLight.CodeExtensions
{
  public static class ObjectExtensionGateway
  {
    public static T VisitWith<T>(this T item, IValueReturningVisitor<T> visitor)
    {
      return visitor.Visit(item);
    }

    public static bool Can<EntityType>(this EntityType item, ISpecification<EntityType> canWhat)
    {
      return canWhat.IsSatisfiedBy(item);
    }

		public static bool Can<EntityType, Param1>(this EntityType item, ISpecification<EntityType, Param1> canWhat, Param1 param1)
		{
			return canWhat.IsSatisfiedBy(item, param1);
		}

    public static bool Can<EntityType, Param1, Param2>(this EntityType item, ISpecification<EntityType, Param1, Param2> canWhat, Param1 param1, Param2 param2)
    {
      return canWhat.IsSatisfiedBy(item, param1, param2);
    }

    public static bool Can<EntityType, Param1, Param2, Param3>(this EntityType item, ISpecification<EntityType, Param1, Param2, Param3> canWhat, Param1 param1, Param2 param2, Param3 param3)
    {
      return canWhat.IsSatisfiedBy(item, param1, param2, param3);
    }

    public static bool Can<EntityType, Param1, Param2, Param3, Param4>(this EntityType item, ISpecification<EntityType, Param1, Param2, Param3, Param4> canWhat, Param1 param1, Param2 param2, Param3 param3, Param4 param4)
    {
      return canWhat.IsSatisfiedBy(item, param1, param2, param3, param4);
    }

    public static bool Cannot<EntityType>(this EntityType item, ISpecification<EntityType> cantWhat)
    {
      return !Can(item, cantWhat);
    }

		public static bool Cannot<EntityType, Param1>(this EntityType item, ISpecification<EntityType, Param1> cantWhat, Param1 param1)
		{
			return !Can(item, cantWhat, param1);
		}

    public static bool Cannot<EntityType, Param1, Param2>(this EntityType item, ISpecification<EntityType, Param1, Param2> cantWhat, Param1 param1, Param2 param2)
    {
      return !Can(item, cantWhat, param1, param2);
    }

    public static bool Cannot<EntityType, Param1, Param2, Param3>(this EntityType item, ISpecification<EntityType, Param1, Param2, Param3> cantWhat, Param1 param1, Param2 param2, Param3 param3)
    {
      return !Can(item, cantWhat, param1, param2, param3);
    }

    public static bool Cannot<EntityType, Param1, Param2, Param3, Param4>(this EntityType item, ISpecification<EntityType, Param1, Param2, Param3, Param4> cantWhat, Param1 param1, Param2 param2, Param3 param3, Param4 param4)
    {
      return !Can(item, cantWhat, param1, param2, param3, param4);
    }

    public static bool Needs<EntityType>(this EntityType item, ISpecification<EntityType> needsWhat)
    {
      return needsWhat.IsSatisfiedBy(item);
    }

    public static bool Needs<EntityType, Param1>(this EntityType item, ISpecification<EntityType, Param1> needsWhat, Param1 param1)
    {
      return needsWhat.IsSatisfiedBy(item, param1);
    }

    public static bool Needs<EntityType, Param1, Param2>(this EntityType item, ISpecification<EntityType, Param1, Param2> needsWhat, Param1 param1, Param2 param2)
    {
      return needsWhat.IsSatisfiedBy(item, param1, param2);
    }

    public static bool Needs<EntityType, Param1, Param2, Param3>(this EntityType item, ISpecification<EntityType, Param1, Param2, Param3> needsWhat, Param1 param1, Param2 param2, Param3 param3)
    {
      return needsWhat.IsSatisfiedBy(item, param1, param2, param3);
    }

    public static bool Needs<EntityType, Param1, Param2, Param3, Param4>(this EntityType item, ISpecification<EntityType, Param1, Param2, Param3, Param4> needsWhat, Param1 param1, Param2 param2, Param3 param3, Param4 param4)
    {
      return needsWhat.IsSatisfiedBy(item, param1, param2, param3, param4);
    }

    public static bool DoesNotNeed<EntityType>(this EntityType item, ISpecification<EntityType> doesntNeedWhat)
    {
      return !Needs(item, doesntNeedWhat);
    }

		public static bool DoesNotNeed<EntityType, Param1>(this EntityType item, ISpecification<EntityType, Param1> doesntNeedWhat, Param1 param1)
		{
			return !Needs(item, doesntNeedWhat, param1);
		}

    public static bool DoesNotNeed<EntityType, Param1, Param2>(this EntityType item, ISpecification<EntityType, Param1, Param2> doesntNeedWhat, Param1 param1, Param2 param2)
    {
      return !Needs(item, doesntNeedWhat, param1, param2);
    }

    public static bool DoesNotNeed<EntityType, Param1, Param2, Param3>(this EntityType item, ISpecification<EntityType, Param1, Param2, Param3> doesntNeedWhat, Param1 param1, Param2 param2, Param3 param3)
    {
      return !Needs(item, doesntNeedWhat, param1, param2, param3);
    }

    public static bool DoesNotNeed<EntityType, Param1, Param2, Param3, Param4>(this EntityType item, ISpecification<EntityType, Param1, Param2, Param3, Param4> doesntNeedWhat, Param1 param1, Param2 param2, Param3 param3, Param4 param4)
    {
      return !Needs(item, doesntNeedWhat, param1, param2, param3, param4);
    }

    public static bool Is<EntityType>(this EntityType item, ISpecification<EntityType> isWhat)
    {
      return isWhat.IsSatisfiedBy(item);
    }

		public static bool Is<EntityType, Param1>(this EntityType item, ISpecification<EntityType, Param1> isWhat, Param1 param1)
		{
			return isWhat.IsSatisfiedBy(item, param1);
		}

    public static bool Is<EntityType, Param1, Param2>(this EntityType item, ISpecification<EntityType, Param1, Param2> isWhat, Param1 param1, Param2 param2)
    {
      return isWhat.IsSatisfiedBy(item, param1, param2);
    }

    public static bool Is<EntityType, Param1, Param2, Param3>(this EntityType item, ISpecification<EntityType, Param1, Param2, Param3> isWhat, Param1 param1, Param2 param2, Param3 param3)
    {
      return isWhat.IsSatisfiedBy(item, param1, param2, param3);
    }

    public static bool Is<EntityType, Param1, Param2, Param3, Param4>(this EntityType item, ISpecification<EntityType, Param1, Param2, Param3, Param4> isWhat, Param1 param1, Param2 param2, Param3 param3, Param4 param4)
    {
      return isWhat.IsSatisfiedBy(item, param1, param2, param3, param4);
    }

    public static bool IsNot<EntityType>(this EntityType item, ISpecification<EntityType> isNotWhat)
    {
      return !Is(item, isNotWhat);
    }

		public static bool IsNot<EntityType, Param1>(this EntityType item, ISpecification<EntityType, Param1> isNotWhat, Param1 param1)
		{
			return !Is(item, isNotWhat, param1);
		}

    public static bool IsNot<EntityType, Param1, Param2>(this EntityType item, ISpecification<EntityType, Param1, Param2> isNotWhat, Param1 param1, Param2 param2)
    {
      return !Is(item, isNotWhat, param1, param2);
    }

    public static bool IsNot<EntityType, Param1, Param2, Param3>(this EntityType item, ISpecification<EntityType, Param1, Param2, Param3> isNotWhat, Param1 param1, Param2 param2, Param3 param3)
    {
      return !Is(item, isNotWhat, param1, param2, param3);
    }

    public static bool IsNot<EntityType, Param1, Param2, Param3, Param4>(this EntityType item, ISpecification<EntityType, Param1, Param2, Param3, Param4> isNotWhat, Param1 param1, Param2 param2, Param3 param3, Param4 param4)
    {
      return !Is(item, isNotWhat, param1, param2, param3, param4);
    }

    public static bool Contains<EntityType>(this EntityType item, ISpecification<EntityType> containsWhat)
    {
      return containsWhat.IsSatisfiedBy(item);
    }

		public static bool Contains<EntityType, Param1>(this EntityType item, ISpecification<EntityType, Param1> containsWhat, Param1 param1)
		{
			return containsWhat.IsSatisfiedBy(item, param1);
		}

    public static bool Contains<EntityType, Param1, Param2>(this EntityType item, ISpecification<EntityType, Param1, Param2> containsWhat, Param1 param1, Param2 param2)
    {
      return containsWhat.IsSatisfiedBy(item, param1, param2);
    }

    public static bool Contains<EntityType, Param1, Param2, Param3>(this EntityType item, ISpecification<EntityType, Param1, Param2, Param3> containsWhat, Param1 param1, Param2 param2, Param3 param3)
    {
      return containsWhat.IsSatisfiedBy(item, param1, param2, param3);
    }

    public static bool Contains<EntityType, Param1, Param2, Param3, Param4>(this EntityType item, ISpecification<EntityType, Param1, Param2, Param3, Param4> containsWhat, Param1 param1, Param2 param2, Param3 param3, Param4 param4)
    {
      return containsWhat.IsSatisfiedBy(item, param1, param2, param3, param4);
    }

    public static bool IsNotIn<EntityType>(this EntityType item, IEnumerable<EntityType> list) where EntityType : class
    {
      return list.DoesNotContain(p => p.Equals(item));
    }

    public static bool IsIn<EntityType, ListType>(this EntityType item, IEnumerable<ListType> list,
                                                  Func<EntityType, ListType, bool> comparer) where EntityType : class
    {
      return list.FirstOrDefault(p => comparer(item, p)) != null;
    }

    public static bool IsNotIn<EntityType, ListType>(this EntityType item, IEnumerable<ListType> list,
                                                     Func<EntityType, ListType, bool> comparer) where EntityType : class
    {
      return !IsIn(item, list, comparer);
    }

    public static bool HasThe<EntityType>(this EntityType item, ISpecification<EntityType> hasWhat)
    {
      return hasWhat.IsSatisfiedBy(item);
    }

		public static bool HasThe<EntityType, Param1>(this EntityType item, ISpecification<EntityType, Param1> hasWhat, Param1 param1)
		{
			return hasWhat.IsSatisfiedBy(item, param1);
		}

    public static bool HasThe<EntityType, Param1, Param2>(this EntityType item, ISpecification<EntityType, Param1, Param2> hasWhat, Param1 param1, Param2 param2)
    {
      return hasWhat.IsSatisfiedBy(item, param1, param2);
    }

    public static bool HasThe<EntityType, Param1, Param2, Param3>(this EntityType item, ISpecification<EntityType, Param1, Param2, Param3> hasWhat, Param1 param1, Param2 param2, Param3 param3)
    {
      return hasWhat.IsSatisfiedBy(item, param1, param2, param3);
    }

    public static bool HasThe<EntityType, Param1, Param2, Param3, Param4>(this EntityType item, ISpecification<EntityType, Param1, Param2, Param3, Param4> hasWhat, Param1 param1, Param2 param2, Param3 param3, Param4 param4)
    {
      return hasWhat.IsSatisfiedBy(item, param1, param2, param3, param4);
    }

		public static bool Has<EntityType>(this EntityType item, ISpecification<EntityType> hasWhat)
		{
			return hasWhat.IsSatisfiedBy(item);
		}

    public static bool Has<EntityType, Param1>(this EntityType item, ISpecification<EntityType, Param1> hasWhat, Param1 param1)
    {
      return hasWhat.IsSatisfiedBy(item, param1);
    }

    public static bool Has<EntityType, Param1, Param2>(this EntityType item, ISpecification<EntityType, Param1, Param2> hasWhat, Param1 param1, Param2 param2)
    {
      return hasWhat.IsSatisfiedBy(item, param1, param2);
    }

    public static bool Has<EntityType, Param1, Param2, Param3>(this EntityType item, ISpecification<EntityType, Param1, Param2, Param3> hasWhat, Param1 param1, Param2 param2, Param3 param3)
    {
      return hasWhat.IsSatisfiedBy(item, param1, param2, param3);
    }

    public static bool Has<EntityType, Param1, Param2, Param3, Param4>(this EntityType item, ISpecification<EntityType, Param1, Param2, Param3, Param4> hasWhat, Param1 param1, Param2 param2, Param3 param3, Param4 param4)
    {
      return hasWhat.IsSatisfiedBy(item, param1, param2, param3, param4);
    }

    public static bool DoesNotHaveThe<EntityType, Param1>(this EntityType item, ISpecification<EntityType, Param1> doesntHaveWhat, Param1 param1)
    {
      return !Can(item, doesntHaveWhat, param1);
    }
  }
}